#include "StdAfx.h"
#include "VectorKey.h"
#include <atlrx.h>
 
class CReg:
	public CAtlRegExp<> 
{
}* CVectorKey::s_pRegExp = NULL;;
int CVectorKey::s_nStatus = 0;
int CVectorKey::s_nNumber = 0;
CVectorKey::CVectorKey(void)
{
	if(s_nNumber==0)
	{
		s_pRegExp = new CReg;
	}
	++s_nNumber;
	memset(m_rgId,0,sizeof(float)*VECTOR_LENGTH);
}

CVectorKey::~CVectorKey(void)
{
	--s_nNumber;
	if(s_nNumber==0)
	{
		delete s_pRegExp;
		s_pRegExp = NULL;
	}
}
bool operator == (const CVectorKey  &cLeft,const CVectorKey  & cRight)
{
	return CVectorKey::Compare(cLeft,cRight)==0;
};

CVectorKey::CVectorKey(const CVectorKey & tmp)
{
	if(s_nNumber==0)
	{
		s_pRegExp = new CReg;
	}
	++s_nNumber;
	for(int i=VECTOR_LENGTH-1;i>=0;i--)
	{
		this->m_rgId[i]=tmp.m_rgId[i];
	}
}
CVectorKey::CVectorKey(const string & tmp)
{
	if(s_nNumber==0)
	{
		s_pRegExp = new CReg;
	}
	++s_nNumber;
	this->FromString(tmp);
}
string CVectorKey::ToString()
{
	string strValue="";
	for(int i=0;i<VECTOR_LENGTH;i++)
	{
		char tmp[128];
		sprintf_s<128>(tmp,"%.6f ",this->m_rgId[VECTOR_LENGTH-i-1]);
		strValue.append(tmp);
	}
	strValue.append(";");
	return strValue;
};
CVectorKey& CVectorKey::operator = (const CVectorKey & tmp)
{
	for(int i=VECTOR_LENGTH-1;i>=0;i--)
	{
		this->m_rgId[i]=tmp.m_rgId[i];
	}
	return *this;
};

bool CVectorKey::FromString(const string & strValue)
{
	if(s_nStatus == 0)
	{
		Init();
	}
	CAtlREMatchContext<> cMatchContext;
	if (!s_pRegExp->Match(strValue.c_str(),&cMatchContext))
	{
		return false;
	}
	if(VECTOR_LENGTH!=cMatchContext.m_uNumGroups)
	{
		return false;
	}				
	else
	{
		char Number[32];
		for(int i = 0;i<VECTOR_LENGTH;i++)
		{
			const CAtlREMatchContext<>::RECHAR* szStart = 0;
			const CAtlREMatchContext<>::RECHAR* szEnd = 0;
			cMatchContext.GetMatch(i, &szStart, &szEnd);
			ptrdiff_t nLength = szEnd - szStart;
			sprintf_s(Number,32,"%.*s", nLength, szStart);
			this->m_rgId[VECTOR_LENGTH-1-i] = (float)strtod(Number,NULL);
		}
		return true;
	}
};


void CVectorKey::Init()
{
	string strReg("[ \\t]*");
	for(int i = 1;i<VECTOR_LENGTH;i++)
	{
		strReg+="{-?(\\d+.\\d+)|(\\d+)}[ \\t]+";
	}
	strReg+="{-?(\\d+.\\d+)|(\\d+)}[ \\t]*;?";
	REParseError status = s_pRegExp->Parse(strReg.c_str());
	if (REPARSE_ERROR_OK != status)
	{
		return ;
	}

	s_nStatus=1;
};
int CVectorKey::GetDistance(const CVectorKey& cLeft,const CVectorKey& cRight)
{
#ifdef COS
	double dTop =0.0,dBottom1 = 0.0,dBottom2 = 0.0;
	for(int i = 0;i<VECTOR_LENGTH;i++)
	{
		dTop+=cLeft.m_rgId[i]*cRight.m_rgId[i];
		dBottom1+=cLeft.m_rgId[i]*cLeft.m_rgId[i];
		dBottom2+=cRight.m_rgId[i]*cRight.m_rgId[i];
	}
	double dRes = dTop/sqrt(dBottom1*dBottom2);

	return D2I((1.0-dRes)*MAX_DIS);
#endif

#ifdef OVERLAP
	double dRes = 0.0,dBottom1 = 0.0,dBottom2 = 0.0;
	for(int i = 0;i<VECTOR_LENGTH;i++)
	{
		dRes+=min(cLeft.m_rgId[i],cRight.m_rgId[i]);
	//	dBottom1+=cLeft.m_rgId[i]*cLeft.m_rgId[i];
	//	dBottom2+=cRight.m_rgId[i]*cRight.m_rgId[i];/sqrt(min(dBottom1,dBottom2))
	}
	return D2I((1-dRes)*MAX_DIS);
#endif
	
#ifdef EUCLIDEN
	double dRes = 0.0;
	for(int i = 0;i<VECTOR_LENGTH;i++)
	{
		dRes+=(cLeft.m_rgId[i]-cRight.m_rgId[i])*(cLeft.m_rgId[i]-cRight.m_rgId[i]);
	}
	return D2I(sqrt(dRes)*MAX_DIS);
#endif
};
int CVectorKey::Compare(const CVectorKey& cLeft,const CVectorKey& cRight)
{
	for(int i=VECTOR_LENGTH-1;i>=0;i--)
	{
		if(abs(cLeft.m_rgId[i],cRight.m_rgId[i])<MINI)
		{
			continue;
		}
		else
		{
			if(cLeft.m_rgId[i]>cRight.m_rgId[i])
			{
				return i+1;
			}
			else
			{
				return -1-i;
			}
		}
	}
	return 0;
};